package com.kinghood.productcenter.manager.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kinghood.infrastructure.api.authority.SysLogModuleEnum;
import com.kinghood.infrastructure.model.KingHoodException;
import com.kinghood.infrastructure.model.KingHoodExceptionUtil;
import com.kinghood.infrastructure.model.constant.CommonConstants;
import com.kinghood.infrastructure.util.UserUtil;
import com.kinghood.infrastructure.util.base.IdGenUtil;
import com.kinghood.infrastructure.util.excel.EasyExcelUtil;
import com.kinghood.infrastructure.util.excel.ExcelExportWriter;
import com.kinghood.productcenter.common.model.dao.product.*;
import com.kinghood.productcenter.common.model.dto.base.SaveFileLocallyDTO;
import com.kinghood.productcenter.common.model.dto.base.SkuQueryPageReqDTO;
import com.kinghood.productcenter.common.model.dto.product.*;
import com.kinghood.productcenter.common.model.dto.sku.GetProductSkuReqDTO;
import com.kinghood.productcenter.common.model.dto.sku.GetSkuRelateIdDTO;
import com.kinghood.productcenter.common.model.dto.sku.ProductSkuReqDTO;
import com.kinghood.productcenter.common.model.dto.sku.UpdateProductSkuReqDTO;
import com.kinghood.productcenter.common.model.vo.base.BaseAttributeVO;
import com.kinghood.productcenter.common.model.vo.product.ProductAttributeListVO;
import com.kinghood.productcenter.common.model.vo.product.ProductDetailVO;
import com.kinghood.productcenter.common.model.vo.product.ProductSkuListVO;
import com.kinghood.productcenter.common.model.vo.product.ProductTemplateInfoVO;
import com.kinghood.productcenter.manager.IProductSkuBaseManager;
import com.kinghood.productcenter.service.async.IAsyncBusinessLogService;
import com.kinghood.productcenter.service.async.IAsyncHuaWeiYunService;
import com.kinghood.productcenter.service.base.IBaseAttributeService;
import com.kinghood.productcenter.service.base.impl.BaseProductTemplateServiceImpl;
import com.kinghood.productcenter.service.product.*;
import com.kinghood.productcenter.service.product.handler.ProductBaseHandler;
import com.kinghood.productcenter.service.product.handler.ProductSkuBaseHandler;
import com.kinghood.sharding.model.BasePage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * description
 *
 * @author zhangFanJun
 * @date 2024-01-22 10:05
 **/
@Slf4j
@RequiredArgsConstructor
@Service
public class ProductSkuBaseManager implements IProductSkuBaseManager {

    private final IProductSkuBaseService productSkuBaseService;
    private final IProductBaseService productBaseService;
    private final BaseProductTemplateServiceImpl productTemplateService;
    private final IProductSkuExtrasBaseService productSkuExtrasBaseService;
    private final IProductSkuSupplierBaseService productSkuSupplierBaseService;
    private final IAsyncBusinessLogService asyncBusinessLogService;
    private final IProductAttributeService productAttributeService;
    private final IBaseAttributeService baseAttributeService;
    private final IDownloadCenterService downloadCenterService;
    private final IBaseAttributeService attributeService;
    private final String uploadPath = "/app/file";
    private final IAsyncHuaWeiYunService asyncUploadHuaWeiYun;
    private final ProductBaseManager productBaseManager;

    @Override
    public ProductDetailVO getProductSku(GetProductSkuReqDTO in) {

        // 商品数据
        ProductDTO productSku = productSkuBaseService.getProductSku(in);
        KingHoodExceptionUtil.isNull(productSku, "商品不存在");

        // 模板
        ProductDetailVO res = new ProductDetailVO();
        ProductTemplateInfoVO template = productTemplateService.getProductTemplateById(productSku.getProductTemplateId(),true);
        res.setProductTemplateId(template.getProductTemplateId());
        res.setNodeList(template.getNodeList());
        res.setDefaultSupplierId(template.getSupplierId());
        res.setSkuStatus(template.getSkuStatus());
        // 模板剔除商品基础信息的模板
        ProductBaseHandler.getSkuTemplate(res);
        // 将商品的value数据封装模板
        if (Objects.nonNull(productSku)) {
            ProductBaseHandler.handleProductTemplateData(res, productSku);
        }

        return res;
    }

    @Override
    public void uploadProductSku(MultipartFile file, HttpServletResponse response) {

        long size = file.getSize();
        String sizeName = ProductBaseHandler.getSizeName(size);
        Long userId = UserUtil.getUserId();
        // 导入
        List<Map<Integer, String>> result = new ArrayList<>();
        StopWatch w = new StopWatch();
        w.start("基础dao数据");
        // 基础dao数据
        BaseProductDaoDTO dao = productBaseService.getBaseProductDao();
        dao.handleMap();
        w.stop();

        try {

            CountDownLatch latch = new CountDownLatch(1);

            String fileName = file.getOriginalFilename();
            String finalFileName = fileName;
            if (!StringUtils.isEmpty(fileName) && fileName.contains(".")) {
                finalFileName = fileName.substring(0, fileName.indexOf("."))
                        + DateUtil.format(new Date(), "yyyy-MM-dd_HH_mm_ss");
            } else {
                finalFileName = fileName + DateUtil.format(new Date(), "yyyy-MM-dd_HH_mm_ss");
            }
            log.info("文件名：{}，文件大小：{}", finalFileName, sizeName);
            w.start("本地备份");
            SaveFileLocallyDTO saveFileLocallyDTO = productBaseManager.saveFileLocally(SysLogModuleEnum.Type.PRODUCT_SKU,file, finalFileName, sizeName);
            w.stop();
            w.start("处理Excel数据");
            Map<Integer, String> head = new HashMap<>();
            EasyExcel.read(saveFileLocallyDTO.getInputStream(), new AnalysisEventListener<Map<Integer, String>>() {
                private static final int BATCH_COUNT = 100;
                private List<Map<Integer, String>> cachedDataList = new ArrayList<>(BATCH_COUNT + 20);
                private String last;
                private Map<String, Integer> fieldMap;
                private Map<Integer, ProductExcelAttributeDTO> headCodeMap;
                private RowFieldRecordDTO rowFieldRecord;

                @Override
                public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
                    log.info("头行数据：{}", headMap);
                    head.putAll(headMap);
                    fieldMap = new HashMap<>(headMap.size());
                    headMap.forEach((x, y) -> {
                        fieldMap.put(y, x);
                    });
                    headCodeMap = ProductSkuBaseHandler.checkExcelHead(headMap, dao);
                    rowFieldRecord = ProductBaseHandler.handleHeadCode(headCodeMap);
                    rowFieldRecord.setUserId(userId);
                }

                @Override
                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                    ReadRowHolder readRowHolder = context.readRowHolder();
                    Integer rowIndex = readRowHolder.getRowIndex();
                    log.info("第{}行数据:{}", rowIndex, data);
                    // 如果数据都是空的，忽略
                    long count = data.values().stream().filter(org.apache.commons.lang3.StringUtils::isNotBlank).count();
                    if (count == 0) {
                        return;
                    }

                    Integer styleNumberIndex = fieldMap.get("款号");
                    String styleNumber = data.get(styleNumberIndex);
                    if (cachedDataList.size() >= BATCH_COUNT && !Objects.equals(last, styleNumber)) {
                        List<Map<Integer, String>> maps = handleExcelData(cachedDataList, headCodeMap, dao, rowFieldRecord);
                        if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(maps)) {
                            result.addAll(maps);
                        }
                        cachedDataList = new ArrayList<>(BATCH_COUNT + 20);
                    }
                    last = styleNumber;
                    cachedDataList.add(data);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    List<Map<Integer, String>> maps = handleExcelData(cachedDataList, headCodeMap, dao, rowFieldRecord);
                    if (com.alibaba.nacos.common.utils.CollectionUtils.isNotEmpty(maps)) {
                        result.addAll(maps);
                    }
                    log.info("excel数据读取结束");
                    latch.countDown();
                }

            }).sheet().doRead();

            latch.await();

            w.stop();
            log.info(w.prettyPrint());
            // 导出
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String exportName = URLEncoder.encode(finalFileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + exportName + ".xlsx");

            EasyExcel.write(response.getOutputStream())
                    .head(ProductBaseHandler.head(head))
                    .sheet("结果")
                    .doWrite(ProductBaseHandler.dataList(result));

            if(Objects.nonNull(saveFileLocallyDTO.getDownloadId())){
                asyncUploadHuaWeiYun.uploadToHuaWeiYun(saveFileLocallyDTO.getDownloadId(), saveFileLocallyDTO.getFilePath());
            }
        } catch (KingHoodException kingHoodException) {
            KingHoodExceptionUtil.throwException(kingHoodException.getMessage());
        } catch (Exception e) {
            log.error("excel文件读取失败：", e);
            KingHoodExceptionUtil.throwException("excel文件读取失败");
        }
    }

    /**
     * 处理excel数据
     * */
    private List<Map<Integer, String>> handleExcelData(List<Map<Integer, String>> cachedDataList, Map<Integer, ProductExcelAttributeDTO> headCodeMap, BaseProductDaoDTO dao, RowFieldRecordDTO rowFieldRecord) {

        if (CollectionUtils.isEmpty(cachedDataList)) {
            return null;
        }
        log.info("开始处理excel数据");
        StopWatch w = new StopWatch();
        w.start("分析数据");

        List<ProductExcelRowDTO> rowList = ProductSkuBaseHandler.handleExcelData(cachedDataList,headCodeMap,dao,rowFieldRecord);

        // 逐个商品解析excel数据
        List<ProductExcelDaoDTO> productDaoList = new ArrayList<>();
        Map<String, List<ProductExcelRowDTO>> productMap = rowList.stream()
                .filter(x->Objects.nonNull(x.getStyleNumber()))
                .collect(Collectors.groupingBy(ProductExcelRowDTO::getStyleNumber));
        productMap.values().forEach(x -> {
            try {
                ProductExcelDaoDTO productExcelDaoDTO = ProductSkuBaseHandler.handleProductSkuData(x, rowFieldRecord,dao);
                if (Objects.nonNull(productExcelDaoDTO)) {
                    productDaoList.add(productExcelDaoDTO);
                }
            } catch (KingHoodException kingHoodException){
                x.forEach(row -> {
                    int size = rowFieldRecord.getSize();
                    ExcelDataInfoDTO one = new ExcelDataInfoDTO();
                    one.setIndex(size);
                    one.setValue("导入失败");
                    one.setBad(true);
                    row.getMap().put(size, one);
                    ExcelDataInfoDTO two = new ExcelDataInfoDTO();
                    two.setIndex(size + 1);
                    two.setValue(kingHoodException.getMessage());
                    two.setBad(true);
                    row.getMap().put(size + 1, two);
                });
            } catch (Exception e) {
                log.error("导入发生异常：", e);
                x.forEach(row -> ProductBaseHandler.badData(row,"导入发生异常",rowFieldRecord.getSize()));
            }
        });

        w.stop();
        w.start("入库");
        // 入库
        productSkuBaseService.saveProductSkuDao(productDaoList);
        w.stop();
        log.info(w.prettyPrint());

        // 返回数据
        ArrayList<Map<Integer, String>> result = new ArrayList<>();
        for (ProductExcelRowDTO row : rowList) {
            HashMap<Integer, String> r = new HashMap<>();
            row.getMap().values().forEach(x -> {
                r.put(x.getIndex(), x.getValue());
            });
            result.add(r);
        }
        return result;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addProductSku(UpdateProductSkuReqDTO in) {

        ProductDTO oldProduct = productBaseService.getProduct(in.getProductId());
        KingHoodExceptionUtil.isNull(oldProduct, "商品不存在");

        List<String> skuCodeList = productSkuBaseService.getSkuCodeList(in.getProductId());
        List<String> allSkuCode =
                in.getSkuList().stream().map(ProductSkuReqDTO::getSkuCode).filter(Objects::nonNull).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(allSkuCode)) {
            Long skuCount = new LambdaQueryChainWrapper<>(productSkuBaseService.getBaseMapper())
                    .eq(ProductSkuBaseDO::getIsDelete, CommonConstants.IS_DELETE_N)
                    .in(ProductSkuBaseDO::getSkuCode, allSkuCode)
                    .notIn(!CollectionUtils.isEmpty(skuCodeList), ProductSkuBaseDO::getSkuCode, skuCodeList)
                    .count();
            KingHoodExceptionUtil.trueThrows(skuCount > 0, "SKU编码已存在");
        }

        // 模板的属性，这里约束删除的属性范围
        List<String> attributeCode = in.getAttributeCode();
        List<Long> templateAttributeIdList = baseAttributeService.getAttributeIdList(attributeCode);

        // 获取旧的数据，对于sku编码相同的需要寻找回
        List<AttributeByProductIdDTO> oldAttributeList = productAttributeService.getAttributeByProductId(in.getProductId());
        Map<String, Long> skuCodeMap = productSkuBaseService.getSkuByProductId(in.getProductId());
        Map<String, Long> oldExtrasMap = productSkuExtrasBaseService.getExtrasByProductId(in.getProductId());
        Map<String, Long> oldSupplierMap = productSkuSupplierBaseService.getSupplierByProductId(in.getProductId());

        // 针对剔除sku的数据需要清除
        List<Long> noDeleteSkuIdList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(in.getSkuList())) {
            Map<String, Long> finalSkuCodeMap = skuCodeMap;
            noDeleteSkuIdList = in.getSkuList().stream().map(sku -> finalSkuCodeMap.get(sku.getSkuCode()))
                    .filter(Objects::nonNull).collect(Collectors.toList());
        }

        // 删除的sku
        productAttributeService.deleteSkuAttribute(in.getProductId(), noDeleteSkuIdList);
        // 删除sku旧数据，非模板的属性不能清理
        productAttributeService.deleteByProductId(in.getProductId(), templateAttributeIdList, ProductAttributeDO.SKU_TYPE_LIST, null);
        productSkuBaseService.deleteByProductId(in.getProductId());
        productSkuExtrasBaseService.deleteByProductId(in.getProductId(), null);
        productSkuSupplierBaseService.deleteByProductId(in.getProductId(), null);

        //所有属性
        Map<String, BaseAttributeVO> attributeVOMap = getBaseAttributeMap();
        // 当存在旧sku，需要id保持不变
        List<ProductSkuBaseDO> skuList = productSkuBaseService.addSku(in.getSkuList(), in.getProductId(), attributeVOMap, skuCodeMap);
        Map<String, ProductSkuBaseDO> skuMap = skuList.stream()
                .filter(Objects::nonNull)
                .filter(x -> Objects.nonNull(x.getSkuCode()))
                .collect(Collectors.toMap(ProductSkuBaseDO::getSkuCode, v -> v, (k1, k2) -> k2));
        productSkuExtrasBaseService.addSkuExtras(in.getSkuExtrasList(), in.getProductId(), skuMap, attributeVOMap, oldExtrasMap);
        productSkuSupplierBaseService.addSkuSupplier(in.getSkuSupplierList(), in.getProductId(), skuMap, attributeVOMap, oldSupplierMap);
        log.info("sku新增==》in:{};;;attributeVOMap:{}", in, attributeVOMap);

        UpdateProductLogDTO logInfo = new UpdateProductLogDTO();
        logInfo.setUserId(UserUtil.getUserId());
        logInfo.setOldSkuCodeMap(skuCodeMap);
        logInfo.handleOldAttribute(oldAttributeList);
        logInfo.setOldProductDTO(oldProduct);
        ProductReqDTO param = new ProductReqDTO();
        ProductBaseReqDTO productBaseReqDTO = new ProductBaseReqDTO(in.getProductId(), oldProduct.getProductBase().getStyleNumber(),
                oldProduct.getProductBase().getStyleName(), oldProduct.getProductBase().getStatus(), null);
        param.setProductBase(productBaseReqDTO);
        param.setSkuList(in.getSkuList());
        param.setSkuPriceList(in.getSkuPriceList());
        param.setSkuExtrasList(in.getSkuExtrasList());
        param.setSkuSupplierList(in.getSkuSupplierList());
        logInfo.setIn(param);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                asyncBusinessLogService.addUpdateProductLog(logInfo, true);
            }
        });

        return in.getProductId();
    }

    private Map<String, BaseAttributeVO> getBaseAttributeMap() {
        List<BaseAttributeVO> attributeVOList = baseAttributeService.getAllAttribute();
        Map<String, BaseAttributeVO> attributeVOMap = new HashMap<>(1);
        if (!CollectionUtils.isEmpty(attributeVOList)) {
            attributeVOMap = attributeVOList.stream()
                    .collect(Collectors.toMap(BaseAttributeVO::getAttributeCode, v -> v, (k1, k2) -> k2));
        }
        return attributeVOMap;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long updateProductSku(UpdateProductSkuReqDTO in) {

        ProductDTO oldProduct = productBaseService.getProduct(in.getProductId());
        KingHoodExceptionUtil.isNull(oldProduct, "商品不存在");

        // 获取旧的数据，对于sku编码相同的需要寻找回
        List<AttributeByProductIdDTO> oldAttributeList = productAttributeService.getAttributeByProductId(in.getProductId());
        Map<String, Long> skuCodeMap = productSkuBaseService.getSkuByProductId(in.getProductId());
        Map<String, Long> oldExtrasMap = productSkuExtrasBaseService.getExtrasByProductId(in.getProductId());
        Map<String, Long> oldSupplierMap = productSkuSupplierBaseService.getSupplierByProductId(in.getProductId());

        // 模板的属性，这里约束删除的属性范围
        GetSkuRelateIdDTO skuRelateIdDTO = productBaseService.getSkuRelateId(in.getProductId(), in.getSku().getSkuCode());
        skuRelateIdDTO.handle();
        if (!CollectionUtils.isEmpty(skuRelateIdDTO.getOtherIdList())) {
            List<String> attributeCode = in.getAttributeCode();
            List<Long> templateAttributeIdList = baseAttributeService.getAttributeIdList(attributeCode);
            productAttributeService.deleteByProductId(in.getProductId(), templateAttributeIdList, null, skuRelateIdDTO.getOtherIdList());
            productSkuExtrasBaseService.deleteByProductId(in.getProductId(), skuRelateIdDTO.getOtherIdList());
            productSkuSupplierBaseService.deleteByProductId(in.getProductId(), skuRelateIdDTO.getOtherIdList());
        }

        Map<String, ProductSkuBaseDO> skuMap = new HashMap<>();
        ProductSkuBaseDO productSkuBaseDO = new ProductSkuBaseDO();
        productSkuBaseDO.setId(skuRelateIdDTO.getId());
        skuMap.put(in.getSku().getSkuCode(), productSkuBaseDO);

        //所有属性
        Map<String, BaseAttributeVO> attributeVOMap = getBaseAttributeMap();
        productSkuExtrasBaseService.addSkuExtras(in.getSkuExtrasList(), in.getProductId(), skuMap, attributeVOMap, oldExtrasMap);
        productSkuSupplierBaseService.addSkuSupplier(in.getSkuSupplierList(), in.getProductId(), skuMap, attributeVOMap, oldSupplierMap);
        log.info("sku修改==》in:{};;;attributeVOMap:{}", in, attributeVOMap);

        UpdateProductLogDTO logInfo = new UpdateProductLogDTO();
        logInfo.setUserId(UserUtil.getUserId());
        logInfo.setOldSkuCodeMap(skuCodeMap);
        logInfo.handleOldAttribute(oldAttributeList);
        logInfo.setOldProductDTO(oldProduct);
        ProductReqDTO param = new ProductReqDTO();
        ProductBaseReqDTO productBaseReqDTO = new ProductBaseReqDTO(in.getProductId(), oldProduct.getProductBase().getStyleNumber(),
                oldProduct.getProductBase().getStyleName(), oldProduct.getProductBase().getStatus(), null);
        param.setProductBase(productBaseReqDTO);
        param.setSkuList(in.getSkuList());
        param.setSkuPriceList(in.getSkuPriceList());
        param.setSkuExtrasList(in.getSkuExtrasList());
        param.setSkuSupplierList(in.getSkuSupplierList());
        logInfo.setIn(param);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                asyncBusinessLogService.addUpdateProductLog(logInfo, true);
            }
        });

        return in.getProductId();
    }

    /**
     * 导出sku
     *
     * @param param    参数
     * @param response 回答
     * @return
     * @author jp
     * @date 2024/01/23 16:46
     */
    @Override
    public void exportSku(SkuQueryPageReqDTO param, HttpServletResponse response) {
        String fileName = StringUtils.isEmpty(param.getFileName()) ? "SKU数据" : param.getFileName();
        String sheetName = StringUtils.isEmpty(param.getSheetName()) ? "SKU" : param.getSheetName();

        if (Objects.isNull(param.getPage())) {
            param.setPage(new BasePage());
            param.getPage().setPageSize(9999l);
        }
        Page<ProductSkuListVO> result = productSkuBaseService.listSku(param);
        Map<Long, Map<String, ProductAttributeListVO>> attributeListVOMap = null;
        if (param.downloadFieldHasAttribute()) {
            List<Long> productList = result.getRecords().stream().map(m -> m.getId()).collect(Collectors.toList());
            // 查询出属性
            attributeListVOMap = productAttributeService.getAllSkuAttributeByCode(param.getRealAttribute(), productList);
        }
        // 要下载的属性code和名称
        Map<String, String> attributeMap = attributeService.getCodeNameMap(param.getRealAttribute());
        ExcelExportWriter exportWriter = new ExcelExportWriter();
        try {
            // 设置文件名
            exportWriter.setSheetName(sheetName);
            exportWriter.setFileName(fileName);

            // 设置内容
            List<List> dataList = new ArrayList<>();
            boolean setHead = true;
            short height = 15;
            for (ProductSkuListVO record : result.getRecords()) {
                if (setHead) {
                    // 设置标题
                    List<String> heads = new ArrayList<>();
                    // sku基础属性
                    for (String baseField : param.getDownloadBaseField()) {
                        String[] annotion = record.getClass().getDeclaredField(baseField).getAnnotation(ExcelProperty.class).value();
                        heads.add(annotion[0]);
                    }
                    // 动态属性标题
                    if (!org.springframework.util.CollectionUtils.isEmpty(attributeListVOMap)) {
                        for (String attribute : param.getRealAttribute()) {
                            if (Objects.nonNull(attributeMap.get(attribute))) {
                                heads.add(Optional.ofNullable(attributeListVOMap.get(record.getId()))
                                        .map(i -> i.get(attribute))
                                        .map(ProductAttributeListVO::getName).orElse(attributeMap.get(attribute)));
                            }
                        }
                    }
                    exportWriter.setOneLineHeads(heads);
                    setHead = false;
                }

                List<Object> columData = new ArrayList<>();
                // sku基础属性
                for (String baseField : param.getDownloadBaseField()) {
                    // 获取对象的属性
                    Field nameField = record.getClass().getDeclaredField(baseField);
                    nameField.setAccessible(true);
                    // 获取对象的属性值
                    Object baseValue = nameField.get(record);

                    columData.add(baseValue);
                }
                // sku动态属性
                if (!org.springframework.util.CollectionUtils.isEmpty(attributeListVOMap)) {
                    for (String attribute : param.getRealAttribute()) {
                        if (Objects.nonNull(attributeMap.get(attribute))) {
                            columData.add(Optional.ofNullable(attributeListVOMap.get(record.getId()))
                                    .map(i -> i.get(attribute))
                                    .map(ProductAttributeListVO::getValue).orElse(""));
                        }
                    }
                }
                dataList.add(columData);
            }
            exportWriter.setDatas(dataList);
            String path = EasyExcelUtil.exportDynamic(response, exportWriter, height, uploadPath);
            DownloadCenterDO downloadCenterDO = new DownloadCenterDO();
            File file = new File(path);
            LocalDateTime now = LocalDateTime.now();
            downloadCenterDO.setId(IdGenUtil.getId())
                    .setFileName(file.getName())
                    .setModule(SysLogModuleEnum.PRODUCT_SKU.getType())
                    .setType(2)
                    .setFileSize(ProductBaseHandler.getSizeName(file.length()))
                    .setUrl(path)
                    .setCreateTime(now)
                    .setUpdateTime(now)
                    .setCreateUserId(UserUtil.getUserId())
                    .setUpdateUserId(UserUtil.getUserId());
            downloadCenterService.save(downloadCenterDO);
            asyncUploadHuaWeiYun.uploadToHuaWeiYun(downloadCenterDO.getId(), file.getAbsolutePath());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
